package com.asyf.demo.common.config;

import com.asyf.demo.common.util.ThreadPoolExecutorMdcWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

@Configuration
@EnableAsync(proxyTargetClass = true)
@Slf4j
public class AsyncConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        //支持MDC的traceId
        ExecutorService executorService = new ThreadPoolExecutorMdcWrapper(10, 200,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());

        //使用自定义的ThreadFactory以支持自定义线程名：CustomizableThreadFactory
        executorService = new ThreadPoolExecutorMdcWrapper(10, 200,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(), new CustomizableThreadFactory("myTask-"));

        //spring封装的执行器 - 不能支持traceId
//        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//        executor.setCorePoolSize(10);
//        executor.setMaxPoolSize(20);
//        executor.setQueueCapacity(1000);
//        executor.setThreadNamePrefix("MyExecutor-");
//        executor.setWaitForTasksToCompleteOnShutdown(false);
//        // 设置拒绝策略
//        executor.setRejectedExecutionHandler((r, e) -> {
//            throw new RejectedExecutionException("Task " + r.toString() +
//                    " rejected from " +
//                    e.toString());
//        });
//        executor.initialize();
//        return executor;
        return executorService;
    }


    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        //return new SimpleAsyncUncaughtExceptionHandler();
        return (ex, method, params) ->
                log.error("Unexpected error occurred invoking async method: " + method +
                        ", args: " + Arrays.toString(params), ex);
    }

}

